package com.carrot.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.carrot.common.core.domain.dto.PointDataDto;
import com.carrot.common.core.domain.dto.StationCellTypeDto;
import com.carrot.common.core.domain.entity.SysStationCellType;
import com.carrot.common.core.domain.entity.SysStationCellReflection;
import com.carrot.common.core.domain.vo.StationCellPointDataVo;
import com.carrot.common.core.domain.vo.StationCellTypeVo;
import com.carrot.common.enums.CellReflectionTypeEnum;
import com.carrot.common.enums.CellTypeEnum;
import com.carrot.common.enums.FillDataEnum;
import com.carrot.common.enums.OnlineEnableEnum;
import com.carrot.common.exception.ServiceException;
import com.carrot.common.mybatis.BaseServiceImpl;
import com.carrot.common.utils.StringUtils;
import com.carrot.common.utils.WrapperUtil;
import com.carrot.system.mapper.SysStationCellReflectionMapper;
import com.carrot.system.mapper.SysStationCellTypeMapper;
import com.carrot.system.service.ISysStationCellReflectionService;
import com.carrot.system.service.ISysStationCellTypeService;
import com.carrot.system.service.ISysStationService;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SysStationCellTypeServiceImpl
        extends BaseServiceImpl<SysStationCellTypeMapper, SysStationCellType>
        implements ISysStationCellTypeService {

//    @Autowired
//    private ISysStationCellReflectionService cellReflectionService;

    @Autowired
    private ISysStationService stationService;

    @Resource
    private SysStationCellReflectionMapper cellReflectionMapper;
    /**
     * 单体点表数据
     */
    @Override
    public List<StationCellPointDataVo> getCellPointData(String stationId,
                                                         String stationAlias,
                                                         String clusterNo,
                                                         Map<String, PointDataDto> cellDataMap) {

        List<SysStationCellType> cellTypeList = this.query()
                .eq("station_id", stationId)
                .orderByAsc("create_time")
                .list();

        List<SysStationCellReflection> cellReflectionList = Lists.newArrayList();

        //总的单体数据
        List<StationCellPointDataVo> stationCellPointDataList = Lists.newArrayList();
        if (CollUtil.isEmpty(cellTypeList) || CollUtil.isEmpty(cellReflectionList)) {
            return stationCellPointDataList;
        }

        // 按照单体类型分组
        Map<String, List<SysStationCellReflection>> cellReflectionMap = cellReflectionList.stream()
                .collect(Collectors.groupingBy(SysStationCellReflection::getCellType));

        // pack和单体的映射关系
        Map<Integer, Integer> packCellMap = stationService.getCellPackMap(stationId);

        for (SysStationCellType cellType : cellTypeList) {
            if (!cellReflectionMap.containsKey(cellType.getCellType())) {
                continue;
            }
            List<SysStationCellReflection> cellReflections = cellReflectionMap.get(cellType.getCellType());

            List<StationCellPointDataVo> cellPointDataList = getStationCellListByReflection(stationId, stationAlias,
                    cellDataMap, cellType.getDescriptionPrefix(),
                    cellType.getCellTypePrefix(), clusterNo, packCellMap, cellReflections);

            stationCellPointDataList.addAll(cellPointDataList);
        }

        return stationCellPointDataList;
    }

    /**
     * 按照单体映射类型，生成单体数据
     */
    private List<StationCellPointDataVo> getStationCellListByReflection(String stationId,
                                                                        String stationAlias,
                                                                        Map<String, PointDataDto> cellDataMap,
                                                                        String descriptionPrefix,
                                                                        String cellTypePrefix,
                                                                        String clusterNo,
                                                                        Map<Integer, Integer> packCellMap,
                                                                        List<SysStationCellReflection> cellReflections) {

        List<StationCellPointDataVo> cellPointDataList = Lists.newArrayList();
        // 单体起始编号
        int cellStartNo = 1;
        //单体类型起始编号
        int cellTypeStartNo = 1;
        String equipmentType = "cell";
        // 生成单体类型
        for (SysStationCellReflection cellReflection : cellReflections) {
            int startNo = cellReflection.getStartNo();

            int endNo = cellReflection.getEndNo();
            int reflectionNum = cellReflection.getReflectionNum();
            String reflectionType = cellReflection.getReflectionType();

            if (CellReflectionTypeEnum.MANY_TO_ONE.getValue().equals(reflectionType)) {
                //  一个温度对应多个单体  n代表几个单体对应一个单体类型
                while (startNo <= endNo) {
                    for (int i = startNo; i <= startNo + reflectionNum; i++) {
                        String propertyName = cellTypePrefix + cellStartNo;
                        String initPropertyName = cellTypePrefix + cellTypeStartNo;
                        // 设备id
                        String equipmentId = stationAlias + "_" + "cluster" + "_" + equipmentType + cellStartNo;
                        //描述
                        String description = descriptionPrefix + cellStartNo;
                        String cluster = stationAlias + "_" + "cluster" + clusterNo;
                        // todo 需要优化
                        String pack = stationAlias + "_" + "pack" + packCellMap.getOrDefault(cellStartNo, 1);

                        StationCellPointDataVo pointDataVo = new StationCellPointDataVo();
                        pointDataVo.setStationId(stationId);
                        pointDataVo.setProtocolName(stationAlias);
                        pointDataVo.setEquipmentId(equipmentId);
                        pointDataVo.setDescription(description);
                        if (cellDataMap.containsKey(description)) {
                            PointDataDto pointDataDto = cellDataMap.get(description);
                            pointDataVo.setEquipmentType(pointDataDto.getEquipmentType());
                            pointDataVo.setInfoObjAddr(pointDataDto.getInfoObjAddr());
//                            pointDataVo.setDataset(pointDataDto.getDataset());
                            pointDataVo.setUnit(pointDataDto.getUnit());
                            pointDataVo.setComment(pointDataDto.getComment());
                        } else {
                            pointDataVo.setEquipmentType("");
                            pointDataVo.setInfoObjAddr("");
                            pointDataVo.setDataset("");
                            pointDataVo.setUnit("");
                            pointDataVo.setComment("");
                        }
                        pointDataVo.setPropertyName(propertyName);
                        pointDataVo.setInitPropertyName(initPropertyName);
                        pointDataVo.setCluster(cluster);
                        pointDataVo.setPack(pack);
                        pointDataVo.setCell(equipmentId);
                        pointDataVo.setFillData(FillDataEnum.YES.getValue());
                        pointDataVo.setOnlineEnable(OnlineEnableEnum.ENABLE.getValue());

                        cellPointDataList.add(pointDataVo);

                        cellStartNo += 1;
                    }
                    startNo += reflectionNum;
                    cellTypeStartNo += 1;
                }
            } else {
                while (startNo <= endNo) {
                    String propertyName = cellTypePrefix + cellStartNo;
                    // 设备id
                    String equipmentId = stationAlias + "_" + "cluster" + "_" + "cell" + cellStartNo;
                    //描述
                    String description = descriptionPrefix + cellStartNo;
                    String cluster = stationAlias + "_" + "cluster" + clusterNo;
                    // todo 需要优化
                    String pack = stationAlias + "_" + "pack" + packCellMap.getOrDefault(cellStartNo, 1);

                    StationCellPointDataVo pointDataVo = new StationCellPointDataVo();
                    pointDataVo.setStationId(stationId);
                    pointDataVo.setProtocolName(stationAlias);
                    pointDataVo.setEquipmentId(equipmentId);
                    pointDataVo.setDescription(description);

                    if (cellDataMap.containsKey(description)) {
                        PointDataDto pointDataDto = cellDataMap.get(description);
                        pointDataVo.setEquipmentType(pointDataDto.getEquipmentType());
                        pointDataVo.setInfoObjAddr(pointDataDto.getInfoObjAddr());
//                        pointDataVo.setDataset(pointDataDto.getDataset());
                        pointDataVo.setUnit(pointDataDto.getUnit());
                        pointDataVo.setComment(pointDataDto.getComment());
                    } else {
                        pointDataVo.setEquipmentType("");
                        pointDataVo.setInfoObjAddr("");
                        pointDataVo.setDataset("");
                        pointDataVo.setUnit("");
                        pointDataVo.setComment("");
                    }
                    pointDataVo.setPropertyName(propertyName);
                    pointDataVo.setInitPropertyName(propertyName);
                    pointDataVo.setCluster(cluster);
                    pointDataVo.setPack(pack);
                    pointDataVo.setCell(equipmentId);
                    pointDataVo.setFillData(FillDataEnum.NO.getValue());
                    pointDataVo.setOnlineEnable(OnlineEnableEnum.ENABLE.getValue());

                    cellPointDataList.add(pointDataVo);

                    cellStartNo += 1;
                    startNo += 1;
                }
            }
        }
        return cellPointDataList;
    }

    /**
     * 获取单体点表配置
     *
     * @param stationId 场站ID
     */
    @Override
    public List<StationCellTypeVo> getCellTypeConfigData(String stationId) {

        List<SysStationCellType> cellTypeList = this.query()
                .eq("station_id", stationId)
                .orderByAsc("create_time")
                .list();

        return WrapperUtil.transform(cellTypeList, StationCellTypeVo.class);
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void add(StationCellTypeDto dto) {

        if (StringUtils.isAnyEmpty(dto.getStationId(), dto.getCellType(),
                dto.getCellTypePrefix(), dto.getDescriptionPrefix())) {
            throw new ServiceException("请求参数校验失败");
        }

        if (null == dto.getCellTypeNum() || dto.getCellTypeNum() == 0) {
            throw new ServiceException("单体类型的数量要大于0");
        }

        // 判断单体的数量
        List<String> cellTypeList = CellTypeEnum.getCellTypeList();
        Integer maxCellNum = cellTypeList.size();

        Long cellNum = this.query().eq("station_id", dto.getStationId()).count();
        if (cellNum >= maxCellNum) {
            throw new ServiceException("已达到场站可配置单体类型的上限");
        }

        if (!cellTypeList.contains(dto.getCellType())) {
            throw new ServiceException("未知的单体类型");
        }
        // 判断是否配置过该单体类型
        long cellTypeNum = this.query()
                .eq("station_id", dto.getStationId())
                .eq("cell_type", dto.getCellType())
                .count();

        if (cellTypeNum > 0) {
            throw new ServiceException("场站配置过该单体类型，不允许重复配置");
        }

        SysStationCellType stationCellPoint = WrapperUtil.transform(dto, SysStationCellType.class);
        this.save(stationCellPoint);
    }


    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void update(StationCellTypeDto dto) {

        if (null == dto.getId() || StringUtils.isEmpty(dto.getStationId())){
            throw new ServiceException("请求参数校验失败");
        }
        SysStationCellType stationCellPoint = WrapperUtil.transform(dto, SysStationCellType.class);
        UpdateWrapper<SysStationCellType> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", dto.getId());
        this.update(stationCellPoint, updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void del(Long id) {

        QueryWrapper<SysStationCellReflection> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("cell_type_id",id);
        SysStationCellReflection cellReflection = cellReflectionMapper.selectOne(queryWrapper);
        if(null != cellReflection){
            throw new ServiceException("有关联单体类型映射，不能删除");
        }
        this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void batchDel(List<Long> ids) {

        QueryWrapper<SysStationCellReflection> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("cell_type_id",ids);
        SysStationCellReflection cellReflection = cellReflectionMapper.selectOne(queryWrapper);
        if(null != cellReflection){
            throw new ServiceException("有关联单体类型映射，不能删除");
        }
        this.removeBatchByIds(ids);
    }
}
